/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package maxent.mr.mapred;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import maxent.mr.writable.FeatureKeyWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Mapper.Context;
import stanford.tagger.DataWordTag;
import stanford.tagger.ExtractorFramesGeneral;
import stanford.tagger.FeatureKey;
import stanford.tagger.History;
import stanford.tagger.TrainerExperiments;

/**
 *
 * @author hadoop
 */
public class FeatureMapper 
        extends Mapper<IntWritable, IntWritable, IntWritable, FeatureKeyWritable>{


    private TrainerExperiments prob;
    private static final String zeroSt = "0";

    @Override
    public void setup(Context context) throws IOException{

        try {
                ObjectInputStream is = new ObjectInputStream(new FileInputStream("targets"));
                prob = (TrainerExperiments) is.readObject();
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e); // bizarre!
            }
    }

    @Override
    public void map(IntWritable key, IntWritable value, Context context) throws IOException, InterruptedException{

        DataWordTag d = prob.getReadDataTagged().get(key.get());
        String ys = d.getY();
        History h = d.getHistory();

        // generate templates
        writeTemplatesNew(h,ys,context,key);

        // generate rare templates
        writeRareTemplatesNew(h, ys, context, key);        

    }

    // Add a new feature key in a hashtable of feature templates
    public void writeTemplatesNew(History h, String tag, Context context, IntWritable index) throws IOException, InterruptedException {
        // Feature templates general

        for (int i = 0; i < prob.getNumFeatsGeneral(); i++) {
          String s = prob.getMaxentTagger().extractors.extract(i, h);

          if (s.equals(zeroSt)) {
            continue;
          } //do not add the feature

          //iterate over tags in dictionary
          if (prob.getMaxentTagger().isAlltags()) {
            int numTags = prob.getMaxentTagger().getTags().getSize();
            for (int j = 0; j < numTags; j++) {

              String tag1 = prob.getMaxentTagger().getTags().getTag(j);

              FeatureKey key = new FeatureKey(i, s, tag1);

              if (!prob.getMaxentTagger().extractors.get(i).precondition(tag1)) {
                continue;
              }

              context.write(index, new FeatureKeyWritable(key));
            }
          } else {
            //only this tag
            FeatureKey key = new FeatureKey(i, s, tag);

            if (!prob.getMaxentTagger().extractors.get(i).precondition(tag)) {
              continue;
            }

            context.write(index, new FeatureKeyWritable(key));
          }
        }        
    }

    private void writeRareTemplatesNew(History h, String tag, Context context, IntWritable index) throws InterruptedException, IOException {
        // Feature templates rare

        if (!(prob.getMaxentTagger().isRare(ExtractorFramesGeneral.cWord.extract(h)))) {
          return;
        }
        int start = prob.getNumFeatsGeneral();
        for (int i = start; i < prob.getNumFeatsAll(); i++) {
          String s = prob.getMaxentTagger().extractorsRare.extract(i - start, h);

          if (s.equals(zeroSt)) {
            continue;
          } //do not add the feature
          if (prob.getMaxentTagger().isAlltags()) {
            int numTags = prob.getMaxentTagger().getTags().getSize();
            for (int j = 0; j < numTags; j++) {

              String tag1 = prob.getMaxentTagger().getTags().getTag(j);

              FeatureKey key = new FeatureKey(i, s, tag1);

              if (!prob.getMaxentTagger().extractorsRare.get(i - start).precondition(tag1)) {
                continue;
              }

              context.write(index, new FeatureKeyWritable(key));
            }
          } else {
            //only this tag
            FeatureKey key = new FeatureKey(i, s, tag);

            if (!prob.getMaxentTagger().extractorsRare.get(i - start).precondition(tag)) {
              continue;
            }

            context.write(index, new FeatureKeyWritable(key));
          }
        }
    }

    
}
